import sys

from PyQt6.QtCore import *
from PyQt6.QtGui import QColor, QFont
from PyQt6.QtWidgets import *

import ui_config


#############################################################################################################################################
#############           程序ui      ##########################################################################################################
#############################################################################################################################################
class UI(QGraphicsScene):
    def __init__(self):
        super().__init__()
        self.widget_items = {}

        self.init_prompt()

    ####################debug########################
    def keyPressEvent(self, event) -> None:
        if event.modifiers() is Qt.KeyboardModifier.ShiftModifier:
            print()

    ##################设置提示########################
    def init_prompt(self):
        button = QPushButton()
        style_sheet = "background-color:rgba(0,0,0,0);color:red;font-size:96px;"
        button.setStyleSheet(style_sheet)
        button.setFixedWidth(ui_config.screen_width)
        button.setVisible(False)
        self.widget_items["prompt"] = self.addWidget(button)
        w = (ui_config.screen_width - self.widget_items["prompt"].widget().size().width()) / 2
        h = (ui_config.screen_height - self.widget_items["prompt"].widget().size().height()) / 2
        self.widget_items["prompt"].setPos(w, h)

    def prompt(self, prompt=""):
        self.widget_items["prompt"].widget().setText(prompt)
        self.widget_items["prompt"].setVisible(bool(prompt))

    ##################设置背景########################
    def set_background(self, path):
        self.views()[0].setStyleSheet(f"border-image:url({ui_config.background_path}/{path}.png)")

    ##################添加图元##########################
    def add_widget_item(self, name, widget):
        self.widget_items[name] = widget
        if isinstance(widget, QWidget):
            widget = self.addWidget(widget)
        self.addItem(widget)

    ##################删除图元##########################
    def delete_widget_item(self, name: str):
        self.widget_items[name].deleteLater()
        self.widget_items.pop(name)

    ##################主界面##########################
    def show_main_window(self, callback):
        window = QWidget()
        view = QGraphicsView(window)
        view.resize(ui_config.screen_width, ui_config.screen_height)
        view.setScene(self)

        self.setSceneRect(0, 0, ui_config.screen_width, ui_config.screen_height)
        self.set_background("1")
        self.init_main_window(callback)

        window.showFullScreen()
        sys.exit(app.exec())

    def init_main_window(self, callback):
        layout = QGraphicsLinearLayout()
        layout.setOrientation(Qt.Orientation.Vertical)

        style_sheet = f"border-image:url({ui_config.figure_path}/button.png);" \
                      "color:red;font-size:64px;"

        button = QPushButton("开始游戏")
        button.setStyleSheet(style_sheet)
        button.clicked.connect(callback)
        layout.addItem(self.addWidget(button))

        button = QPushButton("设置")
        button.setStyleSheet(style_sheet)
        layout.addItem(self.addWidget(button))

        button = QPushButton("退出")
        button.setStyleSheet(style_sheet)
        button.clicked.connect(self.views()[0].parent().deleteLater)
        layout.addItem(self.addWidget(button))

        graphics_widget = QGraphicsWidget()
        graphics_widget.setLayout(layout)

        spacing = int(graphics_widget.childItems()[0].boundingRect().height() / 3)
        graphics_widget.layout().setSpacing(spacing)
        graphics_widget.layout().setContentsMargins(0, 0, 0, 0)

        n = len(graphics_widget.childItems())
        w = int(graphics_widget.childItems()[0].size().width())
        h = int(graphics_widget.childItems()[0].size().height()) * n + spacing * (n - 1)
        x = (ui_config.screen_width - w) / 2
        y = (ui_config.screen_height - h) / 2
        graphics_widget.setPos(x, y)

        self.add_widget_item("main_window_buttons", graphics_widget)

    ##################选择房间########################
    def create_rooms(self):
        layout = QGraphicsLinearLayout()

        style_sheet = f"border-image:url({ui_config.figure_path}/wood.png);" \
                      "color:white;font-size:64px;"

        for i in range(5):
            button = QPushButton("房间0\n人数0")
            button.index = i
            button.setStyleSheet(style_sheet)
            layout.addItem(self.addWidget(button))

        graphics_widget = QGraphicsWidget()
        graphics_widget.setLayout(layout)

        spacing = int(graphics_widget.childItems()[0].boundingRect().width() / 3)
        graphics_widget.layout().setSpacing(spacing)
        graphics_widget.layout().setContentsMargins(0, 0, 0, 0)

        n = len(graphics_widget.childItems())
        w = int(graphics_widget.childItems()[0].size().width()) * n + spacing * (n - 1)
        h = int(graphics_widget.childItems()[0].size().height())
        x = (ui_config.screen_width - w) / 2
        y = (ui_config.screen_height - h) / 2
        graphics_widget.setPos(x, y)

        self.add_widget_item("rooms", graphics_widget)

    def set_rooms_callback(self, event):
        def callback(i):
            event.num = i

        for i in range(self.widget_items["rooms"].layout().count()):
            self.widget_items["rooms"].layout().itemAt(i).widget().clicked.connect(
                    lambda _, x=i: callback(x))

    def fresh_rooms(self, rooms):
        for i in range(self.widget_items["rooms"].layout().count()):
            self.widget_items["rooms"].layout().itemAt(i).widget().setText(f"房间{i}\n人数{rooms[i]}")

    def set_my_room(self, i):
        self.widget_items["rooms"].layout().itemAt(i).widget().setText(f"我的\n房间")

    ##################选择角色########################
    def create_characters(self, players):
        layout = QGraphicsGridLayout()

        style_sheet = f"border-image:url({ui_config.figure_path}/wood.png);" \
                      "color:blue;font-size:64px;"

        max_column = int(pow(len(players), 0.5)) + 1

        button = None
        for i in range(len(players)):
            button = QPushButton(players[i])
            button.name = players[i]
            button.setStyleSheet(style_sheet)
            layout.addItem(self.addWidget(button), int(i / max_column), i % max_column)

        graphics_widget = QGraphicsWidget()
        graphics_widget.setLayout(layout)

        x = (ui_config.screen_width - button.size().width() * max_column) / 2
        y = (ui_config.screen_height - button.size().height() * len(players) / max_column) / 2
        graphics_widget.setPos(int(x), int(y))

        self.add_widget_item("characters", graphics_widget)


    def set_character_callback(self, event):
        def callback(name):
            event.prompt = name

        for i in range(self.widget_items["characters"].layout().rowCount()):
            for j in range(self.widget_items["characters"].layout().columnCount()):
                item = self.widget_items["characters"].layout().itemAt(i, j)
                if item:
                    item.widget().clicked.connect(lambda _, name=item.widget().name: callback(name))

    #####################################################################################################################################
    ######################################        游戏开始            #####################################################################
    ######################################################################################################################################

    #######################初始化logger######################
    def init_logger(self):
        text_edit = QTextEdit()
        text_edit.setHorizontalScrollBarPolicy(Qt.ScrollBarPolicy.ScrollBarAlwaysOff)
        text_edit.setVerticalScrollBarPolicy(Qt.ScrollBarPolicy.ScrollBarAlwaysOff)
        text_edit.setReadOnly(True)
        text_edit.setTextColor(QColor(255, 255, 255))
        font = QFont()
        font.setPointSize(24)
        text_edit.setFont(font)
        text_edit.move(ui_config.logger_x, ui_config.logger_y)
        text_edit.setFixedSize(ui_config.logger_w, ui_config.logger_h)
        style_sheet = "background-color:rgba(0, 0, 0, 0);border:none;"
        text_edit.setStyleSheet(style_sheet)

        self.add_widget_item("text_edit", text_edit)

    def log(self, msg):
        self.widget_items["text_edit"].append(msg)

    ##################初始化战斗场地########################
    def init_combat_field(self):
        def get_combat_field(color):
            style_sheet = f"background-color:{color};border:none;font-size:36px;color:blue;text-align:right"
            widget = QPushButton()
            widget.setStyleSheet(style_sheet)
            widget.setFixedSize(ui_config.combat_field_w, ui_config.combat_field_h_along)
            layout = QHBoxLayout()
            layout.setContentsMargins(0, 0, 0, 0)
            widget.setLayout(layout)

            left_layout = QHBoxLayout()
            layout.addLayout(left_layout)

            center_layout = QHBoxLayout()
            center_layout.setAlignment(Qt.AlignmentFlag.AlignCenter)
            layout.addLayout(center_layout)

            right_layout = QHBoxLayout()
            right_layout.setDirection(QBoxLayout.Direction.RightToLeft)
            layout.addLayout(right_layout)


            return self.addWidget(widget)

        layout = QGraphicsLinearLayout()
        layout.setOrientation(Qt.Orientation.Vertical)
        layout.setSpacing(0)
        layout.setContentsMargins(0, 0, 0, 0)

        colors = ["black", "gray", "red", "green", "red", "gray", "black"]
        for color in colors:
            layout.addItem(get_combat_field(color))

        graphics_widget = QGraphicsWidget()
        graphics_widget.setLayout(layout)
        graphics_widget.setPos(ui_config.combat_field_x, ui_config.combat_field_y)

        self.add_widget_item("combat_field", graphics_widget)

    ############################################################################################################
    ########################################战场卡牌相关##########################################################
    ############################################################################################################
    def add_combat_field_card(self, index, path, align):
        """

        :param index:
        :param path:
        :param align: "right","center",or"left" indicate where to add
        :return:
        """
        alg = {"left": 0, "center": 1, "right": 2}[align]
        button = QPushButton()
        button.setFixedSize(ui_config.combat_field_h_along, ui_config.combat_field_h_along)
        button.setStyleSheet(f"border-image:url({path})")
        self.widget_items["combat_field"].layout().itemAt(index).widget().layout().itemAt(alg).addWidget(button)

        return button

    def remove_combat_field_card(self, index, widget, align):
        alg = {"left": 0, "center": 1, "right": 2}[align]
        self.widget_items["combat_field"].layout().itemAt(index).widget().layout().itemAt(alg).removeWidget(
            widget).deleteLater()

    def move_combat_field_card(self, index_from, index_to, widget, align):
        alg = {"left": 0, "center": 1, "right": 2}[align]
        self.widget_items["combat_field"].layout().itemAt(index_from).widget().layout().itemAt(alg).removeWidget(widget)
        self.widget_items["combat_field"].layout().itemAt(index_to).widget().layout().itemAt(alg).addWidget(widget)

    def add_environment_card(self, index, path):
        return self.add_combat_field_card(index, path, "left")

    def remove_environment_card(self, index, widget):
        self.remove_combat_field_card(index, widget, "left")

    def move_environment_card(self, index_from, index_to, widget):
        self.move_combat_field_card(index_from, index_to, widget, "left")

    def add_avatar_card(self, index, path):
        return self.add_combat_field_card(index, path, "center")

    def remove_avatar_card(self, index, widget):
        self.remove_combat_field_card(index, widget, "center")

    def move_avatar_card(self, index_from, index_to, widget):
        self.move_combat_field_card(index_from, index_to, widget, "center")

    def add_skill_card(self, index, path):
        return self.add_combat_field_card(index, path, "right")

    def remove_skill_card(self, index, widget):
        self.remove_combat_field_card(index, widget, "right")

    def move_skill_card(self, index_from, index_to, widget):
        self.move_combat_field_card(index_from, index_to, widget, "right")

    ##########################################################################################################################
    ##########################################################################################################################
    ##########################################################################################################################
    ##########################战场功能相关###############################################################
    def choose_bool(self, prompt: list[str], event):
        def func(result):
            event.result = result
            b1.deleteLater()
            b2.deleteLater()
            self.prompt()

        confirm, cancel, prompt = prompt
        style_sheet = "color:yellow;font-size:64px;border:none;background-color:rgba(0,0,0,0);"
        button1 = QPushButton(confirm)
        button1.setStyleSheet(style_sheet)
        button1.clicked.connect(lambda: func(True))
        button2 = QPushButton(cancel)
        button2.setStyleSheet(style_sheet)
        button2.clicked.connect(lambda: func(False))

        b1: QGraphicsProxyWidget = self.addWidget(button1)
        y = ui_config.player_me_h + 20
        b1.setPos(ui_config.combat_field_x - b1.size().width() * 1.3, y)
        b2 = self.addWidget(button2)
        b2.setPos(ui_config.combat_field_x + ui_config.combat_field_w + b1.size().width() * 0.3, y)

        self.prompt(prompt)

    #######################选择战场#############################################################
    def choose_field(self, fields, event):
        def call_back(i):
            event.result = i

        for i in fields:
            ui.widget_items["combat_field"].layout().itemAt(i).widget().setText("可选择")
            ui.widget_items["combat_field"].layout().itemAt(i).widget().clicked.connect(lambda self, j=i: call_back(j))

    def remove_choose_field(self, fields):
        for i in fields:
            ui.widget_items["combat_field"].layout().itemAt(i).widget().setText("")
            ui.widget_items["combat_field"].layout().itemAt(i).widget().clicked.disconnect()

app = QApplication(sys.argv)
ui = UI()


############################################################################################################################
#############           玩家ui      #########################################################################################
############################################################################################################################
class BasePlayerUi(QWidget):
    def __init__(self, *args):
        super().__init__(*args)
        style_sheet = "background-color:rgba(0, 0, 0, 0);border:none;"
        self.setStyleSheet(style_sheet)
        layout = QHBoxLayout()
        layout.setSpacing(0)
        layout.setContentsMargins(0, 0, 0, 0)
        self.setLayout(layout)
        self.widget_items = {}
        self.init_widgets()
        self.action = None

    def init_widgets(self):
        self.layout().addWidget(self.get_player())
        self.layout().addWidget(self.get_marks())
        self.layout().addWidget(self.get_skills())
        self.layout().addWidget(self.get_hand_card())
        self.layout().addWidget(self.get_equip())
        self.layout().addWidget(self.get_coin_and_level_and_energy())

    #######################################################################################################
    ########################       初始化组件       #########################################################
    #######################################################################################################
    def get_player(self):
        widget = QWidget()
        widget.setFixedSize(ui_config.player_w, ui_config.player_h)
        layout = QHBoxLayout()
        layout.setAlignment(Qt.AlignmentFlag.AlignBottom)
        layout.setContentsMargins(0, 0, 0, 0)
        widget.setLayout(layout)

        style_sheet = "color:red;font-size:24px;border-image:none;border:none;"
        button = QPushButton()
        button.setStyleSheet(style_sheet)
        layout.addWidget(button, alignment=Qt.AlignmentFlag.AlignLeft)
        self.widget_items["hand_card_num"] = button

        button = QPushButton()
        button.setStyleSheet(style_sheet)
        layout.addWidget(button, alignment=Qt.AlignmentFlag.AlignRight)
        self.widget_items["hp"] = button

        self.widget_items["player"] = widget

        return widget

    def add_mark(self, mark: str):
        style_sheet = "color:red;font-size:32px;background-color:rgba(230,230,230,1);"
        button = QPushButton(mark)
        button.setStyleSheet(style_sheet)
        button.setMaximumSize(20, 20)
        self.widget_items["marks"].layout().addWidget(button)

    def remove_mark(self, mark: str):
        layout = self.widget_items["marks"].layout()

        for i in range(layout.count()):
            if layout.itemAt(i).widget().text().startswith(mark):
                break
        else:
            return False

        item = layout.itemAt(i)
        layout.removeItem(item)
        item.widget().deleteLater()
        return True

    def remove_mark_all(self, mark: str):
        i = 0
        while self.remove_mark(mark):
            i += 1
        return i

    def get_marks(self):
        widget = QWidget()
        layout = QVBoxLayout()
        layout.setAlignment(Qt.AlignmentFlag.AlignTop)
        layout.setContentsMargins(0, 20, 20, 0)
        layout.setSpacing(int(ui_config.player_me_h / 18))
        widget.setLayout(layout)

        self.widget_items["marks"] = widget
        return widget

    def get_skills(self):
        def add_button(name):
            button = QPushButton(name)
            button.setStyleSheet(style_sheet)
            layout.addWidget(button)

        widget = QWidget()
        layout = QVBoxLayout()
        style_sheet = "color:yellow;font-size:24px;"
        add_button("普攻")
        for _ in range(3):
            add_button("未拥有")
        widget.setLayout(layout)

        self.widget_items["skills"] = widget
        return widget

    def add_skill(self, index):
        self.widget_items["skills"].layout().itemAt(index + 1).widget().setText(f"技能{index}:0")

    def get_hand_card(self):
        class ScrollArea(QScrollArea):
            def wheelEvent(self, a0) -> None:
                self.horizontalScrollBar().setValue(self.horizontalScrollBar().value() - a0.angleDelta().y())

        hand_card_area = ScrollArea()
        style_sheet = f"border-image:url({ui_config.figure_path}/wood.png)"
        hand_card_area.setStyleSheet(style_sheet)
        hand_card_area.setFixedWidth(ui_config.player_me_hand_card_w)
        hand_card_area.setHorizontalScrollBarPolicy(Qt.ScrollBarPolicy.ScrollBarAlwaysOff)
        hand_card_area.setVerticalScrollBarPolicy(Qt.ScrollBarPolicy.ScrollBarAlwaysOff)

        widget = QWidget()
        layout = QHBoxLayout()
        layout.setSpacing(3)
        layout.setContentsMargins(0, 0, 0, 0)
        layout.setSizeConstraint(layout.SizeConstraint.SetMinAndMaxSize)
        widget.setLayout(layout)
        hand_card_area.setWidget(widget)

        self.widget_items["hand_cards"] = layout
        return hand_card_area

    def get_coin_and_level_and_energy(self):
        def use_coin():
            self.action = ["use_coin", None]

        style_sheet = "color:yellow;font-size:44px;"
        layout = QVBoxLayout()

        button = QPushButton("金币:0")
        button.setStyleSheet(style_sheet)
        button.clicked.connect(use_coin)
        layout.addWidget(button)

        button = QPushButton("等级:1")
        button.setStyleSheet(style_sheet)
        layout.addWidget(button)

        button = QPushButton("精力:3")
        button.setStyleSheet(style_sheet)
        layout.addWidget(button)
        widget = QWidget()
        widget.setLayout(layout)

        self.widget_items["coin_level_energy"] = widget
        return widget

    def flush_coin(self):
        self.widget_items["coin_level_energy"].layout().itemAt(0).widget().setText(f"金币:{self.coin}")

    def flush_level(self):
        self.widget_items["coin_level_energy"].layout().itemAt(1).widget().setText(f"等级:{self.level}")

    def flush_energy(self):
        self.widget_items["coin_level_energy"].layout().itemAt(2).widget().setText(f"能量:{self.energy}")

    def get_equip(self):
        def add_equip():
            class EquipButton(QPushButton):
                def disable(self):
                    self.setStyleSheet("color:black;")

                def using(self):
                    self.setStyleSheet("color:red;")
                    self.timer_id = self.startTimer(500)

                def timerEvent(self, e) -> None:
                    self.setStyleSheet("color:yellow;")
                    self.killTimer(self.timer_id)

            button = EquipButton()
            button.setFixedWidth(int(ui_config.player_equip_w))
            layout.addWidget(button)

        widget = QWidget()
        style_sheet = f"color:yellow;font-size:32px;border-image:url({ui_config.figure_path}/wood.png)"
        widget.setStyleSheet(style_sheet)
        layout = QVBoxLayout()
        layout.setSpacing(1)
        for _ in range(3):
            add_equip()

        widget.setLayout(layout)

        self.widget_items["equips"] = widget
        return widget

    def get_finish(self):
        def call_back(_):
            self.action = ["phase_end", None]

        style_sheet = "color:yellow;font-size:44px;"
        button = QPushButton("结束\n回合")
        button.setAutoFillBackground(True)
        button.setStyleSheet(style_sheet)
        button.clicked.connect(call_back)

        self.widget_items["phrase_end"] = button
        return button

    #######################################################################################################
    ########################       人物头像相关       #######################################################
    #######################################################################################################
    def set_background(self, name):
        self.widget_items["player"].setStyleSheet(f"border-image:url({ui_config.character_path}/{name}.png)")

    #####################hp,手牌数############################################################################
    def set_hp(self):
        self.widget_items["hp"].setText(str(self.hp))

    def set_hand_card_num(self):
        self.widget_items["hand_card_num"].setText(str(len(self.hand_cards)))


class PlayerUi(BasePlayerUi):
    def __init__(self, *args):
        super().__init__(*args)
        self.move(ui_config.player_x, ui_config.player_y)


class PlayerMeUi(BasePlayerUi):
    def __init__(self, *args):
        super().__init__(*args)
        self.layout().addWidget(self.get_finish())
        self.move(ui_config.player_me_x, ui_config.player_me_y)


#######################################################################################################
########################       卡牌相关           #######################################################
#######################################################################################################
class CardUI(QPushButton):
    def __init__(self, *keys):
        super().__init__(*keys)
        self.setFixedSize(ui_config.card_w, ui_config.card_h)
        self.setVisible(False)
        self.player = None
        self.clicked.connect(self.my_clicked)

    def my_clicked(self):
        if self.player is not None:
            self.player.action = ["click_card", self]

    def set_background(self, id, up):
        if not up:
            id = "card_back"
        self.setStyleSheet(f"font-size:24px;color:red;border-image:url({ui_config.card_path}/{id}.png)")
